package com.yue.springDemo.framework.filter;

import com.yue.springDemo.commons.tools.DateUtils;
import com.yue.springDemo.commons.tools.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * jwt验证
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Value("${jwt.header}")
    private String header;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    /**
     * 过期剩余时间，如果过期剩余时间不足5分钟，则延长token有效期
     */
    private static final int refreshTime = 5 * 60;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserDetailsService theUserDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader(header);
        if (authHeader != null && authHeader.startsWith(tokenHead)) {
            String authToken = authHeader.substring(tokenHead.length());
            String username = jwtTokenUtil.getUsernameFromToken(authToken);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = theUserDetailsService.loadUserByUsername(username);
                if (jwtTokenUtil.validateToken(authToken)) {
                    if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        SecurityContextHolder.getContext().setAuthentication(authentication);

                        // 如果过期时间剩余时间不足，则刷新token
                        if (DateUtils.dateSubtract(new Date(), jwtTokenUtil.getExpiration(authToken)) < refreshTime) {
                            String refreshedToken = jwtTokenUtil.refreshToken(authToken, username);
                            response.setHeader("x-auth-token", refreshedToken);
                        }
                    } else {
                        jwtTokenUtil.del(authToken);
                    }
                }
            } else {
                jwtTokenUtil.del(authToken);
            }
        }
        filterChain.doFilter(request, response);
    }
}
